using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using HengTong.Model.Db.System;
using HengTong.ViewModel._Admin.SysNotificationVms;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using TiaoTaoHelper.Wtm.Interfaces;
using TiaoTaoHelper.Wtm.Models;
using UUIDNext;
using WalkingTec.Mvvm.Core;

namespace HengTong.Services;

public class WorkflowNotificationService(WTMContext context, ILogger<WorkflowNotificationService> logger)
    : IWorkflowNotification
{
    /// <summary>
    /// 添加待办
    /// </summary>
    /// <param name="workflow"></param>
    /// <exception cref="NotImplementedException"></exception>
    public async Task OnStart(SysWorkflow workflow)
    {
        logger.LogInformation("添加待办:{@workflow}", workflow);
        if (workflow.ID == Guid.Empty) workflow.ID = Uuid.NewDatabaseFriendly(Database.SqlServer);
        // 添加审批
        await context.DC.Set<SysWorkflow>().AddAsync(workflow);
        await context.DC.SaveChangesAsync();
        try
        {
            var routeId = await context.DC.Set<SysBillRoute>()
                .AsNoTracking()
                .Where(e => e.CodeType == workflow.ModelType)
                .Select(e => e.ID)
                .FirstOrDefaultAsync();
            var users = new List<string>();
            if (workflow.Type == SysWorkflowType.用户)
            {
                users.Add(workflow.UserCode);
            }
            else if (workflow.Type == SysWorkflowType.角色)
            {
                var roleCode = await context.DC.Set<FrameworkRole>()
                    .AsNoTracking()
                    .Where(e => e.ID == workflow.RoleId)
                    .Select(e => e.RoleCode)
                    .FirstOrDefaultAsync();
                if (!string.IsNullOrWhiteSpace(roleCode))
                {
                    var temp = await context.DC.Set<FrameworkUserRole>()
                        .Where(e => e.RoleCode == roleCode)
                        .Select(e => e.UserCode)
                        .ToListAsync();
                    users.AddRange(temp);
                }
            }
            else if (workflow.Type == SysWorkflowType.部门)
            {
                var groupCode = await context.DC.Set<SysGroup>()
                    .AsNoTracking()
                    .Where(e => e.ID == workflow.GroupId)
                    .Select(e => e.GroupCode)
                    .FirstOrDefaultAsync();
                if (!string.IsNullOrWhiteSpace(groupCode))
                {
                    var temp = await context.DC.Set<FrameworkUserGroup>()
                        .Where(e => e.GroupCode == groupCode)
                        .Select(e => e.UserCode)
                        .ToListAsync();
                    users.AddRange(temp);
                }
            }
            else if (workflow.Type == SysWorkflowType.岗位)
            {
                var temp = await context.DC.Set<SysUserJobPosition>()
                    .Where(e => e.JobPosition.GroupId == workflow.GroupId)
                    .Where(e => e.JobPosition.Roles.Any(x => x.RoleId == workflow.RoleId))
                    .Select(e => e.User.ITCode)
                    .ToListAsync();
                users.AddRange(temp);
            }

            users = users.Distinct().ToList();
            if (users.Count > 0)
            {
                var todoList = await context.DC.Set<SysTodoCenter>()
                    .AsNoTracking()
                    .Where(e => e.WorkflowId == workflow.WorkflowId)
                    .Where(e => users.Contains(e.CreateBy))
                    .ToListAsync();
                foreach (var user in users)
                {
                    // 如果待办已存在，则跳过
                    // 逐级审批中多角色有权限审批这里有可能会有多个相同的待办, 所以需要跳过
                    // 如果创建时间在一分钟以内才跳过, 因为驳回后会重新提交, 如果跳过则会导致待办无法创建
                    var any = todoList.Any(e =>
                        e.CreateBy == user && e.Step == workflow.Step && e.CreateTime > DateTime.Now.AddSeconds(-60));
                    if (any) continue;
                    // 添加待办中心记录
                    var todo = new SysTodoCenter
                    {
                        ID = Uuid.NewDatabaseFriendly(Database.SqlServer),
                        Title =
                            $"[{workflow.SubmitterGroupName}-{workflow.SubmitterName}({workflow.Submitter})]的{workflow.WorkflowName}",
                        RouteId = routeId != Guid.Empty ? routeId : null,
                        BusinessId = workflow.ModelId,
                        ActivityId = workflow.ActivityId,
                        Step = workflow.Step,
                        BusinessType = workflow.WorkflowName,
                        WorkflowId = workflow.WorkflowId,
                        Submitter = workflow.Submitter,
                        Status = TodoStatusEnum.待办,
                        Priority = PriorityEnum.普通,
                        CreateTime = DateTime.Now,
                        DueDate = DateTime.Now.AddDays(1),
                        CreateBy = user,
                        BillCode = workflow.BillCode,
                        Department = workflow.SubmitterGroupName
                    };
                    await context.DC.Set<SysTodoCenter>().AddAsync(todo);
                    // 添加通知记录
                    var notification = new SysNotification
                    {
                        ID = Uuid.NewDatabaseFriendly(Database.SqlServer),
                        Title = $"[{workflow.WorkflowName}]{workflow.BillCode} - {workflow.SubmitterName}",
                        Content =
                            $"您有一个新的审批任务：[{workflow.SubmitterGroupName}-{workflow.SubmitterName}({workflow.Submitter})]的{workflow.WorkflowName}, 单据编号:{workflow.BillCode}，请及时处理。",
                        RouteId = routeId != Guid.Empty ? routeId : null,
                        BusinessType = workflow.WorkflowName,
                        BusinessId = workflow.ModelId,
                        BillCode = workflow.BillCode,
                        Sender = "流程引擎",
                        Receiver = user,
                        Status = NotificationStatusEnum.未读,
                        Priority = PriorityEnum.普通,
                        SendTime = DateTime.Now
                    };
                    var vm = context.CreateVM<SysNotificationVm>();
                    vm.CategoryName = "审批待办";
                    vm.Entity = notification;
                    await vm.DoAddAsync();
                }
            }

            await context.DC.SaveChangesAsync();
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "添加待办和通知消息失败，Workflow: {@workflow}", workflow);
        }
    }

    public async Task OnResume(SysWorkflowHistory history)
    {
        history.ID = Uuid.NewDatabaseFriendly(Database.SqlServer);
        await context.DC.Set<SysWorkflowHistory>().AddAsync(history);
        await context.DC.SaveChangesAsync();
        if (string.IsNullOrWhiteSpace(history.Approver)) return;
        // 标记待办为已协同
        await context.DC.Set<SysTodoCenter>()
            .Where(e => e.Status == TodoStatusEnum.待办)
            .Where(e => e.ActivityId == history.ActivityId)
            .Where(e => e.WorkflowId == history.WorkflowId)
            .Where(e => e.Step == history.Step)
            .Where(e => e.CreateBy != history.Approver)
            .ExecuteUpdateAsync(e =>
                e.SetProperty(x => x.Status, TodoStatusEnum.已协同)
                    .SetProperty(x => x.Approver, history.Approver)
                    .SetProperty(x => x.ApproveResult, history.ApproveResult));
        // 标记待办为已办
        await context.DC.Set<SysTodoCenter>()
            .Where(e => e.Status == TodoStatusEnum.待办)
            .Where(e => e.ActivityId == history.ActivityId)
            .Where(e => e.WorkflowId == history.WorkflowId)
            .Where(e => e.Step == history.Step)
            .Where(e => e.CreateBy == history.Approver)
            .ExecuteUpdateAsync(e =>
                e.SetProperty(x => x.Status, TodoStatusEnum.已办)
                    .SetProperty(x => x.Approver, history.Approver)
                    .SetProperty(x => x.ApproveResult, history.ApproveResult));
        // 标记通知为已读
        await context.DC.Set<SysNotification>()
            .Where(e => e.Status == NotificationStatusEnum.未读)
            .Where(e => e.BusinessId == history.ModelId)
            .ExecuteUpdateAsync(e =>
                e.SetProperty(x => x.Status, NotificationStatusEnum.已读)
                    .SetProperty(x => x.ReadTime, DateTime.Now));

        // 如果是流程撤销,产生消息通知
        if (history.ApproveResult == "流程撤销")
        {
            try
            {
                var routeId = await context.DC.Set<SysBillRoute>()
                    .AsNoTracking()
                    .Where(e => e.CodeType == history.ModelType)
                    .Select(e => e.ID)
                    .FirstOrDefaultAsync();

                var notification = new SysNotification
                {
                    ID = Uuid.NewDatabaseFriendly(Database.SqlServer),
                    Title = $"[{history.WorkflowName}]流程已撤销",
                    Content = $"您的审批流程已被撤销：[{history.WorkflowName}], 撤销原因:{history.ApproveComment ?? "无"}",
                    RouteId = routeId != Guid.Empty ? routeId : null,
                    BusinessType = history.WorkflowName,
                    BusinessId = history.ModelId,
                    Sender = "流程引擎",
                    Receiver = history.Approver,
                    Status = NotificationStatusEnum.未读,
                    Priority = PriorityEnum.普通,
                    SendTime = DateTime.Now
                };

                var vm = context.CreateVM<SysNotificationVm>();
                vm.CategoryName = "审批通知";
                vm.Entity = notification;
                await vm.DoAddAsync();
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "发送流程撤销通知失败, History: {@history}", history);
            }
        }

        await context.DC.SaveChangesAsync();
    }
}